import { SpinLoading, ErrorBlock, ImageViewer, Toast } from "antd-mobile";
import React, { useEffect } from "react";
import { createRoot } from "react-dom/client";
import { user_info, log_all } from "./apis";
import { SourceDB } from "./apis/db";
import { connect, dispatch, getState, IStoreState } from "./store";
import { getRoutes } from "./menus";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { beginLoop, beginSSE, beginWebSocket } from "./handle_message";
import { baseInfo } from "./base_info";
import { __CONFIG__, __PUBLIC_PATH__ } from "./common";

const searchParams = new URL(location.href).searchParams
const root = createRoot(document.getElementById("app"));
root.render(<SpinLoading style={{ '--size': '100px', margin: '100px auto' }} />);

function app() {
  root.render(<App />);
}

let currentDB: InstanceType<typeof SourceDB>;

user_info().then(async function (res) {
  if (res.data?.name) {
    currentDB = new SourceDB(res.data?.username);
    const userMap = await baseInfo();
    const chatrooms = await currentDB.chatroom.toArray()
    dispatch((state) => ({ ...state, loginUser: res.data, userMap, chatrooms }));
    app();
  }
});

export { currentDB };

const _App = (props: IStoreState) => {
  const routes = getRoutes();

  async function init() {
    const old_last = await currentDB.log.orderBy("_id").last();
    const incrementalUpdateCondition = old_last
      ? {
          gmt_modified: {
            $gt: old_last.gmt_created,
          },
        }
      : null;

    const log_all_res = await log_all(incrementalUpdateCondition);

    if (log_all_res.success) {
      await currentDB.log.bulkPut(log_all_res.data);
    }

    const last_id = (await currentDB.log.orderBy("_id").last())?._id;

    if (last_id !== undefined && last_id !== old_last?._id) {
      const chatroom_last_message_map = {};

      const message_send_list = await currentDB.log
        .filter((ele) =>
          ["message_send", "message_cancel", "chatroom_create", "chatroom_update", "chatroom_adduser", "chatroom_deluser", "chatroom_delete"].includes(ele.type)
        )
        .sortBy("gmt_modified");

      for (const ele of message_send_list) {
        let chatroom_id = null;

        switch (ele.type) {
          case "message_send":
          case "message_cancel":
          case "chatroom_adduser":
          case "chatroom_deluser":
          case "chatroom_create":
          case "chatroom_delete":
          case "chatroom_update":
            chatroom_id = ele?.chatroom_id;
            chatroom_last_message_map[chatroom_id] = ele;
            break;

          default:
            break;
        }
      }

      const chatroom_last_message: any = Object.values(chatroom_last_message_map);

      currentDB.chatroom_last_message.bulkPut(chatroom_last_message);
    }

    switch (__CONFIG__?.listenType || searchParams.get('listenType')) {
      case 'loop':
        beginLoop();
        break;
      case 'ws':
        beginWebSocket();
        break;
      default:
        beginSSE();
        break;
    }
  }

  useEffect(() => {
    init();
    addEventListener('error', err => {
      Toast.show({
        icon: 'error',
        content: err.message
      })
    })
  }, []);

  useEffect(function () {
    const onClose = function () {
      if (getState().image) {
        dispatch(state => ({ ...state, image: null }))
      }
    }
    if (props.image) {
      document.addEventListener('click', onClose, true)
    } else {
      document.removeEventListener('click', onClose, true)
    }
  }, [props.image])

  return (
    <>
      <BrowserRouter basename={__PUBLIC_PATH__}>
        <Routes>
          {routes.map((menu) => (
            <Route key={menu.key} path={menu.path} element={<menu.component />} />
          ))}
          <Route path="*" element={<Page404 />} />
        </Routes>
      </BrowserRouter>
      {props.image && <ImageViewer image={props.image} visible />}
    </>
  );
};

const App = connect(getState)(_App)

const Page404 = () => {
  return <ErrorBlock status="empty" title="页面未找到" />;
};
